import inherits from 'inherits'
import PropertiesActivator from 'bpmn-js-properties-panel/lib/PropertiesActivator'
import AsyncCapableHelper from 'bpmn-js-properties-panel/lib/helper/AsyncCapableHelper'
import ImplementationTypeHelper from 'bpmn-js-properties-panel/lib/helper/ImplementationTypeHelper'
import EventDefinitionHelper from 'bpmn-js-properties-panel/lib/helper/EventDefinitionHelper'
import { is, getBusinessObject } from 'bpmn-js/lib/util/ModelUtil'
// bpmn props
import IdProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/IdProps'
import NameProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/NameProps'
import ProcessProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/ProcessProps'
import ExecutableProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/ExecutableProps'
import LinkProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/LinkProps'
import EventProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/EventProps'
import DocumentationProps from 'bpmn-js-properties-panel/lib/provider/bpmn/parts/DocumentationProps'
// camunda props
import ServiceTaskDelegateProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/ServiceTaskDelegateProps'
import UserTaskProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/UserTaskProps'
import ScriptProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/ScriptTaskProps'
import CallActivityProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/CallActivityProps'
import VersionTagProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/VersionTagProps'
import ErrorProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/ErrorEventProps'
import ConditionalProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/ConditionalProps'
import StartEventInitiator from 'bpmn-js-properties-panel/lib/provider/camunda/parts/StartEventInitiator'
import MultiInstanceProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/MultiInstanceLoopProps'
import AsynchronousContinuationProps from 'bpmn-js-properties-panel/lib/provider/camunda/parts/AsynchronousContinuationProps'
import ExternalTaskConfiguration from 'bpmn-js-properties-panel/lib/provider/camunda/parts/ExternalTaskConfigurationProps'
import JobConfiguration from 'bpmn-js-properties-panel/lib/provider/camunda/parts/JobConfigurationProps'
import CandidateStarter from 'bpmn-js-properties-panel/lib/provider/camunda/parts/CandidateStarterProps'
import HistoryTimeToLive from 'bpmn-js-properties-panel/lib/provider/camunda/parts/HistoryTimeToLiveProps'
import Tasklist from 'bpmn-js-properties-panel/lib/provider/camunda/parts/TasklistProps'
import ElementTemplateChooserProps from 'bpmn-js-properties-panel/lib/provider/camunda/element-templates/parts/ChooserProps'
import ElementTemplateCustomProps from 'bpmn-js-properties-panel/lib/provider/camunda/element-templates/parts/CustomProps'
import TitleProps from './parts/title_props'

const PROCESS_KEY_HINT = 'This maps to the process definition key.'
const TASK_KEY_HINT = 'This maps to the task definition key.'

function createGeneralTabGroups(
  element,
  canvas,
  bpmnFactory,
  elementRegistry,
  elementTemplates,
  translate
) {
  element = element.labelTarget || element

  const generalGroup = {
    id: 'general',
    label: translate('常规'),
    entries: []
  }

  let idOptions
  let processOptions

  if (is(element, 'bpmn:Process')) {
    idOptions = { description: PROCESS_KEY_HINT }
  }

  if (is(element, 'bpmn:UserTask')) {
    idOptions = { description: TASK_KEY_HINT }
  }

  if (is(element, 'bpmn:Participant')) {
    processOptions = { processIdDescription: PROCESS_KEY_HINT }
  }

  IdProps(generalGroup, element, translate, idOptions)
  NameProps(generalGroup, element, bpmnFactory, canvas, translate)
  ProcessProps(generalGroup, element, translate, processOptions)
  VersionTagProps(generalGroup, element, translate)
  ExecutableProps(generalGroup, element, translate)
  ElementTemplateChooserProps(
    generalGroup,
    element,
    elementTemplates,
    translate
  )

  const customFieldsGroups = ElementTemplateCustomProps(
    element,
    elementTemplates,
    bpmnFactory,
    translate
  )

  const detailsGroup = {
    id: 'details',
    label: translate('详情'),
    entries: []
  }
  ServiceTaskDelegateProps(detailsGroup, element, bpmnFactory, translate)
  UserTaskProps(detailsGroup, element, translate)
  ScriptProps(detailsGroup, element, bpmnFactory, translate)
  LinkProps(detailsGroup, element, translate)
  CallActivityProps(detailsGroup, element, bpmnFactory, translate)
  EventProps(detailsGroup, element, bpmnFactory, elementRegistry, translate)
  ErrorProps(detailsGroup, element, bpmnFactory, translate)
  ConditionalProps(detailsGroup, element, bpmnFactory, translate)
  StartEventInitiator(detailsGroup, element, translate)

  const multiInstanceGroup = {
    id: 'multiInstance',
    label: translate('Multi Instance'),
    entries: []
  }
  MultiInstanceProps(multiInstanceGroup, element, bpmnFactory, translate)

  const asyncGroup = {
    id: 'async',
    label: translate('Asynchronous Continuations'),
    entries: []
  }
  AsynchronousContinuationProps(asyncGroup, element, bpmnFactory, translate)

  const jobConfigurationGroup = {
    id: 'jobConfiguration',
    label: translate('Job Configuration'),
    entries: [],
    enabled: isJobConfigEnabled
  }
  JobConfiguration(jobConfigurationGroup, element, bpmnFactory, translate)

  const externalTaskGroup = {
    id: 'externalTaskConfiguration',
    label: translate('External Task Configuration'),
    entries: [],
    enabled: isExternalTaskPriorityEnabled
  }
  ExternalTaskConfiguration(externalTaskGroup, element, bpmnFactory, translate)

  const candidateStarterGroup = {
    id: 'candidateStarterConfiguration',
    label: translate('Candidate Starter Configuration'),
    entries: []
  }
  CandidateStarter(candidateStarterGroup, element, bpmnFactory, translate)

  const historyTimeToLiveGroup = {
    id: 'historyConfiguration',
    label: translate('History Configuration'),
    entries: []
  }
  HistoryTimeToLive(historyTimeToLiveGroup, element, bpmnFactory, translate)

  const tasklistGroup = {
    id: 'tasklist',
    label: translate('Tasklist Configuration'),
    entries: []
  }
  Tasklist(tasklistGroup, element, bpmnFactory, translate)

  const documentationGroup = {
    id: 'documentation',
    label: translate('Documentation'),
    entries: []
  }
  DocumentationProps(documentationGroup, element, bpmnFactory, translate)

  const groups = []
  groups.push(generalGroup)
  customFieldsGroups.forEach(function(group) {
    groups.push(group)
  })
  groups.push(detailsGroup)
  groups.push(externalTaskGroup)
  groups.push(multiInstanceGroup)
  groups.push(asyncGroup)
  groups.push(jobConfigurationGroup)
  groups.push(candidateStarterGroup)
  groups.push(historyTimeToLiveGroup)
  groups.push(tasklistGroup)
  groups.push(documentationGroup)

  return groups
}

function createAuthorityTabGroups(element) {
  const editAuthorityGroup = {
    id: 'edit-authority',
    label: '编辑权限',
    entries: []
  }

  TitleProps(editAuthorityGroup, element)

  return [editAuthorityGroup]
}

function isExternalTaskPriorityEnabled(element) {
  const businessObject = getBusinessObject(element)

  if (
    is(element, 'bpmn:Process') ||
    (is(element, 'bpmn:Participant') && businessObject.get('processRef'))
  ) {
    return true
  }

  const externalBo = ImplementationTypeHelper.getServiceTaskLikeBusinessObject(
    element
  )
  const isExternalTask =
    ImplementationTypeHelper.getImplementationType(externalBo) === 'external'

  return (
    !!ImplementationTypeHelper.isExternalCapable(externalBo) && isExternalTask
  )
}

function isJobConfigEnabled(element) {
  const businessObject = getBusinessObject(element)

  if (
    is(element, 'bpmn:Process') ||
    (is(element, 'bpmn:Participant') && businessObject.get('processRef'))
  ) {
    return true
  }

  const bo = getBusinessObject(element)
  if (
    AsyncCapableHelper.isAsyncBefore(bo) ||
    AsyncCapableHelper.isAsyncAfter(bo)
  ) {
    return true
  }

  if (is(element, 'bpmn:Event')) {
    return !!EventDefinitionHelper.getTimerEventDefinition(element)
  }

  return false
}

function CustomPropertiesProvider(
  eventBus,
  canvas,
  bpmnFactory,
  elementRegistry,
  elementTemplates,
  translate
) {
  PropertiesActivator.call(this, eventBus)

  this.getTabs = element => {
    const generalTab = {
      id: 'general',
      label: '常规',
      groups: createGeneralTabGroups(
        element,
        canvas,
        bpmnFactory,
        elementRegistry,
        elementTemplates,
        translate
      )
    }
    const authorityTab = {
      id: 'authority',
      label: '权限',
      groups: createAuthorityTabGroups(element)
    }
    return [generalTab, authorityTab]
  }
}

CustomPropertiesProvider.$inject = [
  'eventBus',
  'canvas',
  'bpmnFactory',
  'elementRegistry',
  'elementTemplates',
  'translate'
]

inherits(CustomPropertiesProvider, PropertiesActivator)

export default CustomPropertiesProvider
